/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Project2.cs342.project1.mathNotebook.data;

import java.io.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import Project2.cs342.project1.mathNotebook.notebook.NotebookEntry;

/**
 *
 * @author Kevin
 */
public class LocalEncryptionReader {
    private SecretKey secretKey;
    private String secretKeyString;
    User user;

    public LocalEncryptionReader(User user, BigInteger encryptedSecretKeyString){
        this.user = user;
        secretKeyString = decodeEncryptedSecretKeyString(encryptedSecretKeyString);
        secretKey = generateSecretKey(secretKeyString);
	
    }


        /**
     * Generates the DES SecretKey object
     *
     * @param DES password as a String
     * @return DES key as a SecretKey object
     */
    private SecretKey generateSecretKey(String password){
        SecretKey desKey = null;
        try{
            byte[] desKeyData = password.getBytes();
            DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            desKey = keyFactory.generateSecret(desKeySpec);


        }
        catch (InvalidKeySpecException e) {System.err.println(e);}
        catch (InvalidKeyException e) {System.err.println(e);}
        catch (NoSuchAlgorithmException e) {
            System.err.println(e);
            e.printStackTrace();
        }


        return desKey;
    }

        /**
     * Reads an encrypted file and outputs it as an .gzip file with the same name.
     *
     * @param String name of the encrypted file
     * @return Boolean of whether or not the read was successful
     */
    public boolean readEncryptedFile(String encryptedFile){
        boolean readSuccess = true;
        if(encryptedFile.substring(encryptedFile.length()-8).equals(".encrypt")){
            try {
                FileInputStream fin = new FileInputStream(new File(encryptedFile));
                InputStream in = null;
                DataOutputStream dout = null;
                Cipher des = null;


                encryptedFile = encryptedFile.substring(0, encryptedFile.length()-8);

                FileOutputStream fout = new FileOutputStream(new File(encryptedFile + ".gzip"));

                // Use Data Encryption Standard cipher
                des = Cipher.getInstance("des");
                des.init(Cipher.DECRYPT_MODE, secretKey);

                dout = new DataOutputStream(fout);

                byte[] input = new byte[fin.available()];
                while (true) {
                    int bytesRead = fin.read(input);
                    if (bytesRead == -1) break;
                    byte[] output = des.update(input);
                    if (output != null) dout.write(output) ;
                }

                byte[] output = des.doFinal();
                if (output != null) dout.write(output);
                fin.close();
                dout.flush();
                dout.close();

            }

            catch (InvalidKeyException e) {System.err.println(e); readSuccess = false;}
            catch (NoSuchAlgorithmException e) {
                System.err.println(e);
                e.printStackTrace();
                readSuccess = false;
            }
            catch (NoSuchPaddingException e) {System.err.println(e); readSuccess = false;}
            catch (BadPaddingException e) {System.err.println(e); readSuccess = false;}
            catch (IllegalBlockSizeException e) {System.err.println(e); readSuccess = false;}
            catch (IOException e) {System.err.println(e); readSuccess = false;}
        }
        else{
            readSuccess = false;
        }

        return readSuccess;

    }


     /**
     * Decrypts the encrypted DES key using the User's private key
     *
     * @param BigInteger value of the encrypted DES key
     * @return DES key as a String
     */
    private String decodeEncryptedSecretKeyString(BigInteger encryptedSecretKeyString){

        String secretKeyString = null;

         try {

            InputStream bin = new ByteArrayInputStream(encryptedSecretKeyString.toByteArray() );

            // Use RSA cipher
            KeyFactory keyFactory = KeyFactory.getInstance("rsa");
            Cipher rsa = Cipher.getInstance("rsa");
            Key rsa_pri_key = null;
            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(user.getRsaPrivateKey());

            rsa_pri_key = keyFactory.generatePrivate(priKeySpec);
            rsa.init(Cipher.DECRYPT_MODE, rsa_pri_key);

            secretKeyString = new String("");

            byte[] input = new byte[64];
            while (true) {
                int bytesRead = bin.read(input);
                if (bytesRead == -1) break;
                byte[] output = rsa.update(input, 0, bytesRead);
                if (output != null) secretKeyString = secretKeyString.concat(new String(output)) ;
            }

            byte[] output = rsa.doFinal();
            if (output != null) secretKeyString = secretKeyString.concat(new String(output));
            bin.close();



        }
        catch (InvalidKeySpecException e) {System.err.println(e);}
        catch (InvalidKeyException e) {System.err.println(e);}
        catch (NoSuchAlgorithmException e) {
            System.err.println(e);
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e) {System.err.println(e);}
        catch (BadPaddingException e) {System.err.println(e);}
        catch (IllegalBlockSizeException e) {System.err.println(e);}
        catch (IOException e) {System.err.println(e);}


        return secretKeyString;
    }
	
	
}
